package com.graduate.cec.service;


import com.alibaba.fastjson.JSON;
import com.graduate.cec.mapper.AdminMapper;
import com.graduate.cec.mapper.UserMapper;
import com.graduate.cec.pojo.dto.LoginDTO;
import com.graduate.cec.pojo.vo.AdminLoginVO;
import com.graduate.cec.pojo.vo.AdminSimpleVO;
import com.graduate.cec.pojo.vo.UserLoginVO;
import com.graduate.cec.security.JwtConst;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class LoginService implements UserDetailsService {
    @Autowired
    AdminMapper adminMapper;
    @Autowired
    UserMapper userMapper;

    @Value("${kbs.jwt.secret-key}")
    private String secretKey;

    //实现认证
    @Autowired
    AuthenticationManager authenticationManager;

    private String role;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        log.info("即将取数据库找信息");
        log.info("username:{}", username);
        AdminLoginVO admin = new AdminLoginVO();
        UserLoginVO user = new UserLoginVO();
        if("管理员".equals(role)){
            admin = adminMapper.selectLoginInfoByPhone(username);
        }else{
            user = userMapper.selectLoginInfoByPhone(username);
        }

        log.info("admin=" + admin);
        log.info("user=" + user);
        if (admin == null || user == null) {
            throw new BadCredentialsException("登录失败用户名不存在");
        }
        log.info("查询到匹配的管理员数据，需要将此数据转换为UserDetails并返回");
        UserDetails userDetails;
        if("管理员".equals(role)){
            userDetails = User.builder()
                    .username(admin.getPhone())
                    .password(admin.getPassword())
                    .accountExpired(false)
                    .accountLocked(false)
                    .disabled(admin.getIsEnable() != 0)
                    .credentialsExpired(false)
                    .authorities(admin.getPermissions().toArray(new String[]{}))
                    .build();
        }else{
            userDetails = User.builder()
                    .username(user.getPhone())
                    .password(user.getPassword())
                    .accountExpired(false)
                    .accountLocked(false)
                    .disabled(user.getIsEnable() != 1)
                    .credentialsExpired(false)
                    .authorities(user.getPermissions().toArray(new String[]{}))
                    .build();
        }


        log.info("转换得到UserDetails=" + userDetails);

        return userDetails;


    }

    public String login(LoginDTO loginDTO, String roleTemple) {
        role = roleTemple;

        log.info("AdminServiceImpl.login()");
        log.info("将执行自动匹配密码");

        Authentication authentication = new UsernamePasswordAuthenticationToken(
                loginDTO.getPhone(),
                loginDTO.getPassword()
        );

        Authentication authenticate = authenticationManager.authenticate(authentication);

        User user = (User) authenticate.getPrincipal();

        //Claims
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtConst.KEY_PERMISSIONS, JSON.toJSONString(user.getAuthorities()));
        claims.put(JwtConst.KEY_USERNAME, user.getUsername());

        String jwt = Jwts.builder()
                .setHeaderParam(Header.CONTENT_TYPE, "HS256")
                .setHeaderParam(Header.TYPE, Header.JWT_TYPE)
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + 60*24 * 60 * 1000))
                //Signature  由算法和密钥(secret key)这两部分组成
                .signWith(SignatureAlgorithm.HS256, secretKey)
                //打包生成
                .compact();
        log.info(jwt);
        return jwt;
    }

    public AdminSimpleVO selectSimplePersonal(){
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String phone = (String) principal;
        log.info("selectSimplePersonal phone:{}",phone);
        return adminMapper.selectSimplePersonal(phone);
    }


}
